package org.dromara.javalin;

import cn.dev33.satoken.SaManager;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import io.javalin.config.JavalinConfig;
import io.javalin.config.RouterConfig;
import io.javalin.plugin.Plugin;
import org.dromara.javalin.annotation.WebHandler;
import org.dromara.javalin.handler.SaTokenContextHandler;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.function.Consumer;

public class SaTokenJavalinPlugin extends Plugin<Void> {
    private static final Logger log = LoggerFactory.getLogger(SaTokenJavalinPlugin.class);

    private final SaTokenJavalinPluginConfig saTokenJavalinPluginConfig;

    public SaTokenJavalinPlugin(Consumer<SaTokenJavalinPluginConfig> consumer) {
        saTokenJavalinPluginConfig = new SaTokenJavalinPluginConfig();
        consumer.accept(saTokenJavalinPluginConfig);
        SaManager.setConfig(saTokenJavalinPluginConfig);
    }

    @Override
    public void onInitialize(@NotNull JavalinConfig config) {
        var routerConfig = config.router;
        this.registerSaTokenContextHandler(routerConfig);
        this.registerWebHandler(routerConfig);
    }

    private void registerSaTokenContextHandler(RouterConfig routerConfig) {
        var saTokenContextHandler = new SaTokenContextHandler();
        routerConfig.mount(saTokenContextHandler);
    }

    private void registerWebHandler(RouterConfig routerConfig) {
        if (CharSequenceUtil.isEmpty(saTokenJavalinPluginConfig.getScanPackage())) {
            throw new RuntimeException("请配置扫描包名");
        }
        var webHandlerClasses = ClassUtil.scanPackageByAnnotation(saTokenJavalinPluginConfig.getScanPackage(), WebHandler.class);
        if (CollUtil.isNotEmpty(webHandlerClasses)) {
            for (Class<?> webHandlerClass : webHandlerClasses) {
                var annotation = AnnotationUtil.getAnnotation(webHandlerClass, WebHandler.class);
                var methods = ClassUtil.getDeclaredMethods(webHandlerClass);
                if (annotation == null || ArrayUtil.isEmpty(methods)) {
                    continue;
                }
                var webHandler = ReflectUtil.newInstance(webHandlerClass);
                var endpointGroup = new SaTokenEndpointGroup(annotation, webHandler, methods);
                routerConfig.apiBuilder(endpointGroup);
            }
        }
    }

    @Override
    public void onStart(@NotNull JavalinConfig config) {
        log.info("starting sa-token javalin plugin.");
    }

}
